#include "EventLoop.h"
#include <sys/epoll.h>
#include <unistd.h>
#include <fcntl.h>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/eventfd.h>
#include <iostream>
#include <pthread.h>
#include <sched.h>
#define MAX_EVENTS 10

std::shared_ptr<EventLoop> EventLoop::getInstance()
{
    static std::shared_ptr<EventLoop> instance = nullptr;
    static std::mutex singletonMutex;
    if (instance == nullptr)
    {
        std::unique_lock<std::mutex> lock(singletonMutex);
        if (instance == nullptr)
        {
            instance = std::shared_ptr<EventLoop>(new EventLoop());
            instance->start();
        }
    }
    return instance;
}

EventLoop::EventLoop()
    : epoll_fd(-1)
{
}

// 更新channel通道 epoll_ctl add/mod/del
void EventLoop::update_event(int operation, Channel *channel)
{
    epoll_event event;
    bzero(&event, sizeof event);
    int fd = channel->getfd();
    event.events = channel->events_;
    event.data.ptr = channel;
    if (::epoll_ctl(epoll_fd, operation, fd, &event) < 0)
    {
        LOG_ERROR("epoll_ctl %d error: %s\n",operation,strerror(errno));
    }
}

void EventLoop::start()
{
    // 创建epoll实例
    epoll_fd = epoll_create1(0);
    if (epoll_fd == -1)
    {
        perror("Epoll creation failed");
        return;
    }

    // 启动处理客户端请求的线程
    clientHandlerThread = std::thread(&EventLoop::handleClient, this);
    // 给线程命名
    pthread_setname_np(clientHandlerThread.native_handle(), "epoll");
    // 等待线程结束
    clientHandlerThread.detach();
}

int EventLoop::setNonBlocking(int sockfd)
{
    int flags = fcntl(sockfd, F_GETFL, 0);
    if (flags == -1)
    {
        perror("fcntl F_GETFL failed");
        return -1;
    }
    if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
    {
        perror("fcntl F_SETFL failed");
        return -1;
    }
    return 0;
}
void EventLoop::handleClient()
{
    // 事件循环
    while (true)
    {
        int n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        if (n == -1)
        {
            perror("Epoll wait failed");
            break;
        }
        for (int i = 0; i < n; ++i)
        {
             
            if (events[i].data.ptr != nullptr)
            {
                Channel *channel = static_cast<Channel *>(events[i].data.ptr);
                channel->m_handle_call_back(&events[i]);
            }
            else
            {
                std::cout << "No Channel " << std::endl;
            }
        }
    }
}
